from __future__ import with_statement
import sys, imaplib, email, uuid, logging, ConfigParser, codecs, urllib, os
from xml.etree import ElementTree as etree
from datetime import datetime
from wsgiref.simple_server import make_server, WSGIServer, WSGIRequestHandler
from cStringIO import StringIO

from templates import *

logging.root.setLevel(logging.INFO)

PLAINTYPE = "text/plain"
HTMLTYPE = "text/html"
TNEFTYPE = "application/ms-tnef"

try:
   from html2text import html2text
except ImportError, e:
   logging.warn("html2text not found: entries will miss summaries")
   html2text = lambda x: ""

try:
   import tnef
except ImportError, e:
   raise ImportError("pytnef package is now a requirement; please download and install!")
   

def get_message_data(config, new=False, flagged=False, since=None, before=None):
   globals().update(config)
   mailserver = imaplib.IMAP4(server)
   mailserver.login(username, password)
   number_msgs = mailserver.select(folder)
   query = []
   if new == True:
      query.append("UNSEEN")
   if flagged:
      query.append("FLAGGED")
   if since:
      query.append("SINCE %s" % since)
   if before:
      query.append("BEFORE %s" % before)
   
   response, data = mailserver.search(None, "(%s)" % ' '.join(query))
   print response, data
   response, data = mailserver.fetch(','.join(data[0].split()), "(RFC822.HEADER)")
   data = data[::2]
   messages = []
   for i in data:
      messages.append(email.message_from_string(i[1]))
   return messages


def get_messages(config):
   "query for messages in a given folder"
   globals().update(config)
   mailserver = imaplib.IMAP4(server)
   mailserver.login(username, password)
   number_msgs = mailserver.select(folder)
   
   response, data = mailserver.search(None, query)
   if response != "OK":
      raise Exception("search failed: %s" % response)

   messages = data[0].split()
   logging.info("found %i messages, retrieving..." % len(messages))

   for message in messages:

      response, data = mailserver.fetch(message, '(RFC822)')
      if response != "OK":
         raise Exception("fetch failed: %s" % response)
      try:
         msg = email.message_from_string(data[0][1])
      except Exception, e:
         logging.error("problem parsing message: %s" % e)

      msg_info = (msg["From"], msg["Subject"][:10] + " ..")
      logging.info("message from %s: %s" % msg_info)

      if msg.is_multipart():
         logging.info("multipart message")
         contenttype, charset, payload = tnef.util.choose_payload(msg)
         if contenttype == TNEFTYPE:
            with tnef.util.data2file(payload) as tnef_file:
               # omitted preference kwparam defaults to ("rtf", "htm", "txt")
               payload = tnef.getBodyFromString(tnef_file, extract=True)
      else:
         logging.info("single-part message")
         payload = msg.get_payload(decode=True)

      try:
         payload = payload.decode(charset)
         logging.info("decoded %s payload from %s" % (contenttype, charset))
      except:
         charset = charset or "unknown charset"
         logging.warn("could not decode %s from %s" % (contenttype, charset))

      msg.set_payload(payload)
      msg.set_type(contenttype)
      msg.set_charset(charset)

      yield msg
         
   mailserver.close()
   mailserver.logout()      


def get_atom_feed(messages, config):
   "return an atom feed"
   
   config["updated"] = datetime.now().isoformat()
   config["id"] = uuid.uuid5(uuid.NAMESPACE_URL, config["link"])
   feed = atom10body.safe_substitute(config)
   
   entries = []
   for msg in messages:
      data = {}
      data["id"] = urllib.quote(msg["message-id"])
      data["link"] = "%s/%s" % (config["link"], data["id"])
      data["title"] = msg["subject"]
      data["author"] = msg["from"]
      data["updated"] = msg["date"]

      # payload is prebuilt/selected by get_messages
      data["content"] = msg.get_payload()
      summary = data["content"][:50]
      try:
         data["summary"] = html2text(summary) + " ..."
      except:
         logging.error("could not convert HTML to plaintext")
         data["summary"] = ""
      try:
         entry = atom10item.substitute(data)
         entries.append(entry)
      except Exception, e:
         types = ["%s:%s" % (key, type(val)) for key, val in data.items()]
         logging.warn("could not subst: %s: %s" % (types,e))

   return feed + "\n".join(entries) + "</feed>"


def write_feed(feed):
   f = codecs.open("latest.xml", "w", "utf-8")
   f.write(feed)
   f.close()
 

class ProxyServer(WSGIServer):
   "server that provides rss representation of imap messages"
   
   def __init__(self, addr="", port=8080, inifile="config.ini"):
      WSGIServer.__init__(self, (addr, port), WSGIRequestHandler)
      self.set_app(self)
      self.inifile = inifile
      self.feed = None
      self.load_config()
      
   
   def load_config(self):
      "load config section"
      self.config = {}
      parser = ConfigParser.ConfigParser()
      config = open(self.inifile)
      parser.readfp(config)
      for section in parser.sections():
         data = dict(parser.items(section))
         self.config[section] = data


   def __call__(self, environ, start_response):
      "callable wsgi application to handle /folderpath/new requests"
      start_response('200 OK', [('content-type', 'application/atom+xml')])
      
      #path = environ["PATH_INFO"].split('/')
      #folder = '/'.join(path[1:-1])
      #query = path[-1]
      
      if not self.feed:
         messages = get_messages(self.config["email"])
         feed = get_atom_feed(messages, self.config["feed"])
         self.feed = feed.encode("UTF-8")
      
      write_feed(self.feed)
      
      return self.feed


if __name__=="__main__":

   httpd = ProxyServer("", 8080)
   httpd.handle_request()
   """
   parser = ConfigParser.ConfigParser()
   configfile = open("config.ini")
   parser.readfp(configfile)
   config = dict(parser.items("email"))
   msgs = get_message_data(config, since="30-Jun-2005") #, flagged=True)
   for m in msgs:
      print m["From"]
   """
